package org.gnu.williamjoy.cellular;

import java.util.Random;

public class CellularGrid {

    private final int width;
    private final int height;
    private boolean data[][];
    private boolean image[][];
    private int total = -1;
    private int max_neighbour = 2;
    private int min_neighbour = 2;

    public CellularGrid(int width) {
        this(width, width);
    }

    public CellularGrid(int width, int height) {
        if (width < 1 || height < 1) {
            throw new java.lang.IllegalArgumentException(
                    "CellularGrid width and height should be greater that 0");
        }
        this.width = width;
        this.height = height;
        data = new boolean[width][height];
        image = new boolean[width][height];
    }

    public void shuffle() {
        Random random = new Random();
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                data[i][j] = random.nextDouble() > 0.99;
            }
        }
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public boolean isAlive(int x, int y) {
        return data[x][y];
    }

    public boolean isGonnaAlive(int x, int y) {
        int count = data[x][y] ? -1 : 0;
        for (int i = x - 1; i <= x + 1; i++) {
            for (int j = y - 1; j <= y + 1; j++) {
                if (data[(i + width) % width][(j + height) % height])
                    count++;
            }
        }
        return count <= this.max_neighbour && count >= this.min_neighbour;
    }

    public void step() {
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                image[i][j] = isGonnaAlive(i, j);
            }
        }
        total = 0;
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                data[i][j] = image[i][j];
                if (data[i][j])
                    total++;
            }
        }
    }

    public int getTotal() {
        return total;
    }

    public void bounce() {
        this.max_neighbour = 5 - this.max_neighbour;
        this.min_neighbour = this.max_neighbour;
    }
}
